﻿using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace Longbow.Net
{
    /// <summary>
    /// Scoket 客户端接口
    /// </summary>
    public interface ISocketClient : IDisposable
    {
        /// <summary>
        /// 获得 SocketClientStatus 状态
        /// </summary>
        SocketClientStatus Status { get; }

        /// <summary>
        /// 获得 异常错误信息
        /// </summary>
        Exception Exception { get; }

        /// <summary>
        /// 获得 本地节点实例
        /// </summary>
        IPEndPoint LocalEndPoint { get; }

        /// <summary>
        /// 获得 远端节点实例
        /// </summary>
        IPEndPoint RemoteEndPoint { get; }

        /// <summary>
        /// 关闭连接方法
        /// </summary>
        void Close();

        /// <summary>
        /// 打开连接方法 异步执行 callback 在另外线程上执行
        /// </summary>
        /// <param name="host">主机 IP 地址</param>
        /// <param name="port">主机 Port 端口</param>
        /// <param name="receiveCallback">接收数据回调函数</param>
        /// <param name="optionConfigure">连接配置回调函数</param>
        /// <param name="cancellationToken">连接取消令牌</param>
        Task<bool> ConnectAsync(string host, int port, Action<ISocketClient, byte[]> receiveCallback = null, Action<SocketConnectOptions> optionConfigure = null, CancellationToken cancellationToken = default);

        /// <summary>
        /// 异步发送数据到远程计算机，发送数据前请确保 socket 已经连接
        /// </summary>
        /// <param name="data">要发送的数据</param>
        /// <param name="optionConfigure">用于更新配置项</param>
        /// <param name="cancellationToken">取消发送Token</param>
        /// <returns>同步发送后接收到的数据 字节数组</returns>
        Task<bool> SendAsync(byte[] data, Action<SocketSendAsyncOptions> optionConfigure = null, CancellationToken cancellationToken = default);

        /// <summary>
        /// 同步发送数据
        /// </summary>
        /// <param name="data">要发送的数据 字节数组</param>
        /// <param name="optionConfigure">SocketSendOptions 配置回调函数</param>
        /// <param name="cancellationToken">取消发送Token</param>
        /// <remarks></remarks>
        /// <returns></returns>
        byte[] Send(byte[] data, Action<SocketSendOptions> optionConfigure = null, CancellationToken cancellationToken = default);
    }
}
